package org.ainlolcat.ainscience.statistics.handlers.hitran;

import org.ainlolcat.ainscience.utils.*;
import org.ainlolcat.ainscience.column.Column;
import org.ainlolcat.ainscience.entity.Entity;
import org.ainlolcat.ainscience.statistics.handlers.hitran.instfunc.GaussInstrumentalFunction;
import org.ainlolcat.ainscience.statistics.handlers.hitran.instfunc.InstrumentalFunction;
import org.ainlolcat.ainscience.statistics.handlers.hitran.instfunc.PsdVoigt1InstrumentalFunction;
import org.ainlolcat.ainscience.statistics.handlers.hitran.soax.AxSpectrTemperatureFinder;
import org.ainlolcat.ainscience.statistics.handlers.hitran.sobx.BxSpectrTemperatureFinder;
import org.ainlolcat.ainscience.statistics.StatisticHandler;
import org.ainlolcat.ainscience.statistics.StatisticStorage;
import org.ainlolcat.ainscience.tools;
import org.apache.log4j.Logger;
import org.jdom.Element;

import javax.swing.*;
import java.util.*;
import java.util.List;

/**
 * @author ainlolcat
 * Date: 12/12/11
 */
public class SpectrTStatistic implements StatisticHandler{
    private static Logger log = Logger.getLogger(SpectrTStatistic.class);
    double T;
    //double A=35664.07, w=1.51335,  y0=0; //ava2048-2 bc600mk 738nm
    static double g_A=22478.48, g_w=0.52113,  g_y0=0;                           //ava2048-1 bc600mk 772nm
    //static double psd_A=1.67E12, psd_w=0.60814,  psd_y0 =3.39E9,  mu = 0.07335; //ava2048-1 bc600mk 772nm
    static double psd_A=1, psd_w=0.60814,  psd_y0 =0,  mu = 0.07335; //ava2048-1 bc600mk 772nm
    boolean psdVoigt = false;

    double A, w, y0;
    double T0 = 200, T2 = 400, dT = 10;
    SpectrTemperatureFinder stf;
    double[][] data = new double[3][];

    public JPanel getRenderer() {
        return new SpectrTStatisticRenderer(this);
    }

    public Hashtable<String,String> getStatistic(Entity entity, Integer columnID) {
        A=g_A; w=g_w;  y0=g_y0;
        return getStatistic(entity,columnID,T0,T2,dT,new GaussInstrumentalFunction(y0, A, w));
    }

    public Hashtable<String, String> getStatistic(Entity entity, Integer columnID, Element params) {
        if (params.getChild("mu")!=null){
            mu = tools.parseDouble(params.getChild("mu").getAttributeValue("value"));
            psdVoigt = true;
        }
        if (psdVoigt){
            A=psd_A; w=psd_w;  y0= psd_y0;
        } else {
            A=g_A; w=g_w;  y0=g_y0;
        }
        if (params.getChild("A")!=null){
            A = tools.parseDouble(params.getChild("A").getAttributeValue("value"));
        }
        if (params.getChild("w")!=null){
            w = tools.parseDouble(params.getChild("w").getAttributeValue("value"));
        }
        if (params.getChild("y0")!=null){
            y0 = tools.parseDouble(params.getChild("y0").getAttributeValue("value"));
        }
        if (params.getChild("T0")!=null){
            T0 = tools.parseDouble(params.getChild("T0").getAttributeValue("value"));
        }
        if (params.getChild("T2")!=null){
            T2 = tools.parseDouble(params.getChild("T2").getAttributeValue("value"));
        }
        if (params.getChild("dT")!=null){
            dT = tools.parseDouble(params.getChild("dT").getAttributeValue("value"));
        }

        String functionClass = XMLUtils.getSafeString4Children(params, "fClass", null);
        if (functionClass != null){
            try {
                Class<InstrumentalFunction> ifClass = (Class<InstrumentalFunction>) Class.forName(functionClass);
                String sParameters = XMLUtils.getSafeString4Children(params, "fParameters", null);
                String[] pA = sParameters.split(";");
                double[] parameters = new double[pA.length];
                for (int i=0;i<pA.length;i++){
                    parameters[i] = Double.parseDouble(pA[i]);
                }
                InstrumentalFunction function = ifClass.newInstance();
                function.setParameters(parameters);
                return getStatistic(entity,columnID,T0,T2,dT,function);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            if (psdVoigt){
                return getStatistic(entity,columnID,T0,T2,dT,new PsdVoigt1InstrumentalFunction(y0, A, w, mu));
            } else {
                return getStatistic(entity,columnID,T0,T2,dT,new GaussInstrumentalFunction(y0, A, w));
            }
        }
    }

    private Hashtable<String, String> getStatistic(Entity entity, Integer columnID,
                                                   double T0, double T2, double dT,
                                                   InstrumentalFunction func ){
        Hashtable<String,String> answer = new Hashtable<String, String>();
        Column cy = entity.getColumnById(columnID);
        Column cx = entity.getXColumn(cy.getAxis());
        if (cx!=null&&cx.isNumeric()&&cy.isNumeric()){
            try{

                double[] x = cx.getDoubleRepresentation();
                double[] y = cy.getDoubleRepresentation();
                if (x[0]<1000){
                    if ((x[0]<750)||(x[x.length-1]>780)){
                        List<Double> nx = new ArrayList<Double>();
                        List<Double> ny = new ArrayList<Double>();
                        for (int i=0;i<x.length;i++){
                            if ((x[i]>750)&&(x[i]<780)){
                                nx.add(x[i]);
                                ny.add(y[i]);
                            }
                        }
                        x=new double[nx.size()];
                        y=new double[nx.size()];
                        for (int i=0;i<nx.size();i++){
                            x[i] = nx.get(i);
                            y[i] = ny.get(i);
                        }
                        data[0] = x;
                        data[1] = y;
                    }
                    stf = new BxSpectrTemperatureFinder();
                    T = stf.getT(x,y,func,T0,T2,dT);
                    double[] generated = stf.getSpectr(T, func, x, y);
                    data[2] = generated;
                    answer.put("T(b-x), K", new Double(T).toString());
                    answer.put("b-x shift", String.valueOf(stf.getShift()));
                    double [] eps = ArraysUtil.getNormalizedDifference(data[0], data[1], data[2]);
                    answer.put("b-x eps", String.valueOf(eps[1]));
                    StatisticStorage.getInstance().registerHandler(entity,"T(b-x), K",this);
                    return answer;
                } else {
                    stf = new AxSpectrTemperatureFinder();
                    T = stf.getT(x, y, func, T0, T2, dT);
                    double[] generated = stf.getSpectr(T,func, x,y);
                    data[0] = x;
                    data[1] = y;
                    data[2] = generated;
                    answer.put("T(a-x), K", new Double(T).toString());
                    answer.put("a-x shift", String.valueOf(stf.getShift()));
                    double [] eps = ArraysUtil.getNormalizedDifference(data[0], data[1], data[2]);
                    answer.put("a-x eps", String.valueOf(eps[1]));
                    StatisticStorage.getInstance().registerHandler(entity,"T(a-x), K",this);
                    return answer;
                }
            }catch(Exception e){
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }

}


